/*
    Project:        Home Power Control
    File:           HPCWindVane.cpp
    Author:         christian@karunamusic.at
    Date:           11.2014
    Description:    Sensor to measure the direction of the wind.
                    The sensor works with 8 reed-switches connected to different resistors.
                    The magnet can close 2 switches so that we have 16 positions.
                    The output of the voltage-divider is measured via MCP3008 (A2D).
 */

#include <unistd.h>
#include <limits>
#include <iostream>
#include <sstream>
#include <linux/spi/spidev.h>
#include <wiringPi.h>
#include "globals.h"
#include "HPCWindVane.h"

using namespace std;

HPCWindVane::HPCWindVane( unsigned long id, unsigned int channel, unsigned int pin, unsigned int interval )
    : HPCThreadedSensor(id,pin,interval), m_Channel(channel)
{
    PROFILE_THIS;

    m_Old = (unsigned int)0;
    ostringstream devstr;
    devstr << "/dev/spidev0." << m_Channel;
    string dev( devstr.str() );

    m_A2D = new HPCMCP3008( dev, SPI_MODE_0, 1000000, 8 );
}

HPCWindVane::~HPCWindVane()
{
    PROFILE_THIS;
}

string HPCWindVane::asString() const
{
    stringstream s;
    s << "Sensor " << Name()<<" (Type " << (unsigned int)Type() << ", ID " << ID() << ") on channel " << m_Channel << ", pin " << Pin();
    return s.str();
}

void HPCWindVane::Measure()
{
    PROFILE_THIS;

    int i;
    int volt;
    unsigned char data[3];
    static int dirVolt[] = { 210, 270, 300, 410, 600, 790, 930,1310,
                            1490,1930,2030,2260,2530,2670,2860,3050 };
    static unsigned int dirs[] = {6,4,5,8,7,10,9,2,3,12,11,16,1,14,15,13};
    static float degs[] = { 112.5,67.5,90.0,157.5,135.0,202.5,180.0,22.5,
                            45.0,247.5,225.0,337.5,0.0,292.5,315.0,270.0};
    static vector<string> wtxt = {"","N","NNE","NE","ENE","E","ESE","SE","SSE","S","SSW","SW","WSW","W","WNW","NW","NNW"};

    data[0] = 1;
    data[1] = (m_Pin + 8) << 4;
    data[2] = 0;

    m_A2D->spiWriteRead( data, sizeof(data) );

    volt = ((((data[1] & 3) << 8) + data[2]) * 3300) / 1024;

    for ( i = 0; i < 16; i++ )
    {
        if ( volt <= dirVolt[i] )
            break;
    }

    if ( i >= 16 )
    {
        m_Value = (unsigned int)0;
        m_Degrees = 0.0;
    }
    else
    {
        m_Value = dirs[i];
        m_Degrees = degs[i];
    }

    m_DirTxt = wtxt[(unsigned int)m_Value];
}

bool HPCWindVane::hasChanged()
{
    PROFILE_THIS;

    Measure();
    LOG( debug, "Measured value: " << (string)m_Value << " (" << m_Degrees << "deg = '" << m_DirTxt << "')" );

    return (m_Value != m_Old);
}
